<?php

namespace App\Jobs;

use App\Models\ParkingLot\DeviceStatusLog;
use App\Models\Common\Constant;
use App\Models\ParkingLot\Handlers\ParkEnterHandler;
use App\Models\ParkingLot\Handlers\ParkOutHandler;
use App\Models\ParkingLot\Lane;
use App\Models\ParkingLot\MthCar;
use App\Models\ParkingLot\MthCarLane;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class HandleDeviceNotifyJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    private $act;
    private $data;

    const ACT_RECORDED_PARKING_LOGS = 'parking_logs';
    const ACT_FAILED_SYNC_CAR = 'sync_car';
    const ACT_FAILED_DEVICE_STATUS = 'device_status';

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct(array $data, $act)
    {
        $this->act = $act;
        $this->data = $data;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $data = $this->data;

        $timestamp = \Arr::get($data, 'timestamp');
        if (strlen($timestamp) === 13) {
            $dateTime = Carbon::createFromTimestampMs($timestamp);
        } else {
            $dateTime = Carbon::parse($timestamp);
        }

        switch ($this->act) {
            case self::ACT_RECORDED_PARKING_LOGS:
                // 设备序列号
                $sn = \Arr::get($data, 'sn');
                // 车牌
                if (!$plate = \Arr::get($data, 'guid')) {
                    return;
                }

                if (strlen($plate) >= 15) {
                    \Log::channel('parking')->error($plate . ' 车牌号有误');
                    return;
                }

                if ($lane = Lane::where('device_sn', $sn)->first()) {

                    if (!$offline = \Arr::get($data, 'offline', 0)) {
                        if ($dateTime->diffInMinutes(now()) > 20) {
                            $offline = 1;
                        }
                        else {
                            if ($dateTime->diffInMinutes(now()) > 2) {
                                $dateTime = now()->toDateTimeString();
                            }
                        }
                    }

                    // 是否为月租车
                    $deviceWhite = false;
                    if ($mthCar = MthCar::where('parking_lot_id', $lane->parking_lot_id)
                        ->where('car_no', $plate)->first()) {
                        if (Carbon::parse($mthCar->end_at)->endOfDay() > now()) {
                            if (MthCarLane::where([
                                'mth_car_id' => $mthCar->id,
                                'lane_id' => $lane->id,
                                'status' => 1
                            ])->first()) {
                                $deviceWhite = true;
                            }
                        }
                    }

                    $pic = \Arr::get($data, 'photoUrl');
                    $plateType = \Arr::get($data, 'plateType');
                    $idx = \Arr::get(Lane::IDX, $lane->category);

                    // 进场
                    if (1 === $idx) {
                        $handler = new ParkEnterHandler();
                        $handler->into($sn, $plate, $plateType, $dateTime, $deviceWhite, $deviceWhite, $pic, $offline);
                    }
                    // 出场
                    if (2 === $idx) {
                        // 无牌车
                        if (strpos($plate, '无') !== false) {
                            return;
                        }
                        if (strpos($plate, '未识别') !== false) {
                            return;
                        }
                        if ($plate === '-') {
                            return;
                        }

                        if (!$offline) {
                            $cacheKey = $lane->id . Constant::LANE_OUT_CAR;
                            \Cache::put($cacheKey, [
                                'car_no' => $plate,
                                'out_pic' => $pic
                            ], now()->addMinutes(5));
                        }

                        $handler = new ParkOutHandler();
                        $handler->out($sn, $plate, $plateType, $dateTime, $deviceWhite, $deviceWhite, $pic, $offline);

                    }
                } else {
                    \Log::channel('parking')->error($plate . ' 识别推送设备序列号(' . $sn . ')的车道不存在');
                }

                break;
            case self::ACT_FAILED_SYNC_CAR: //车牌下发
                if (!$lane = Lane::where('device_sn', \Arr::get($data, 'sn'))->first()) {
                    return;
                }
                // 设备状态更新
                if (!$lane->gate_state) {
                    $lane->update(['gate_state' => 1]);
                }
                // 车牌号
                $guid = \Arr::get($data, 'guid');
                if ($guid) {
                    if (!$mthCar = MthCar::where('parking_lot_id', $lane->parking_lot_id)->where('car_no', $guid)->first()) {
                        return;
                    }

                    $result = intval(\Arr::get($data, 'result'));  //0- 失败 1-成功

                    if ($result === 1) {//下发成功
                        $msg = '';
                    }
                    else {
                        $msg = \Arr::get($data, 'msg') ?: '下发失败';
                    }

                    $relation = MthCarLane::where([
                        'mth_car_id' => $mthCar->id,
                        'lane_id' => $lane->id
                    ])->first();
                    if ($relation) {
                        $relation->update([
                            'status' => $result,
                            'msg' => $msg
                        ]);
                    } else {
                        MthCarLane::create([
                            'mth_car_id' => $mthCar->id,
                            'lane_id' => $lane->id,
                            'status' => $result,
                            'msg' => $msg
                        ]);
                    }
                }

                break;
            case self::ACT_FAILED_DEVICE_STATUS:
                $sn = \Arr::get($data, 'deviceSn');
                if ($lane = Lane::where('device_sn', $sn)->first()) {
                    $bool = 1 === \Arr::get($data, 'online');
                    if (boolval($lane->gate_state) !== $bool) {
                        if ($lane->gate_state) {
                            \Log::channel('parking')->info('设备离线' . $sn);
                        } else {
                            \Log::channel('parking')->info('设备上线' . $sn);
                        }
                        $lane->update(['gate_state' => $bool]);

                        DeviceStatusLog::create([
                            'lane_name' => $lane->name,
                            'lane_id' => $lane->id,
                            'device_sn' => $lane->device_sn,
                            'status' => $bool,
                            'parking_lot_name' => optional($lane->parkingLot)->name ?: '',
                            'parking_lot_id' => optional($lane->parkingLot)->id ?: '',
                        ]);
                    }
                }
                break;
        }
    }
}
